<template>
  <!--
        visible: 是否显示弹窗
        close-on-click-modal: 是否可以点击model关闭弹窗
        close-on-press-escape: 是否可以通过按下ESC关闭弹窗
        show-close: 是否显示关闭按钮
        title: 弹窗名称
        close: 弹窗关闭的回调事件
    -->
  <el-dialog
    ref="dialog"
    :visible.sync="visible"
    :close-on-click-modal="closeOnClickOutside"
    :modal-append-to-body="false"
    :close-on-press-escape="closeOnClickOutside"
    :append-to-body="true"
    :show-close="!hideCloseBtn"
    :title="dialogTitle"
    @close="onClosed"
    :class="isClass"
  >
    <header class="header" v-if="showHeader">
      <!-- <img src="@assets/icon/index-logo.png" :alt="$t('Meet.huipeitong')" /> -->
      <i class="el-icon-close" @click="closeDialog"></i>
    </header>
    <!--
            is: 子组件DOM
            dialog-data: 传入子组件的数据
            set-title: 子组件设置弹窗的名称
            set-close-bundle: 设置弹窗关闭的回调参数
            complete: 关闭弹窗
        -->
    <component
      :is="contentComponentDom"
      ref="dialogContent"
      :dialog-data="dialogData"
      @set-title="setTitle"
      @close-dialog="closeDialog"
    >
    </component>
  </el-dialog>
</template>

<script>
/**
 * 执行流程：
 * refShowDialog 外部打开弹窗，注册DOM，(传入参数，注册onClose事件)(可选) ->
 * closeDialog 组件内部关闭弹窗事件 ->
 * setCloseBundle 关闭弹窗前，若有参数，保存回调参数 ->
 * close 关闭弹窗 ->
 * onClosed 弹窗关闭的回调事件 ->
 * callCloseListeners 弹窗注册的onClose事件执行
 */
import Vue from "vue";

export default {
  name: "DialogModule",
  data() {
    return {
      isClass: "",
      contentComponentDom: null,
      dialogData: {},
      dialogTitle: "",

      closeOnClickOutside: false,
      // 弹窗关闭动画开始的事件
      // 参数为关闭时的弹框type，和closeBundle对象
      closeListeners: [],
      // showDialog时返回出去用于注册回调方法的对象
      showDialogResult: {
        onClose: (callback) => this.closeListeners.push(callback),
      },
      // 关闭弹框时传入回调函数的数据
      closeBundle: {},
      // 是否显示弹窗，双向绑定到el-dialog上的变量
      visible: false,
      // 是否展示右上角关闭按钮
      hideCloseBtn: false,
      // 是否是手动点击右上角关闭按钮
      clickClose: true,
      showHeader: false,
    };
  },
  computed: {},
  methods: {
    /**
     * 显示指定弹框
     * @param {dom} dialogDom 弹窗的DOM
     * @param {string?} dialogTitle 弹窗的title
     * @param {object?} dialogData 要传递给窗口内容组件的数据
     */
    refShowDialog(
      dialogDom,
      dialogTitle,
      dialogData = {},
      showClose,
      showHeader
    ) {
      this.setupComponent(dialogDom, dialogData);
      this.visible = true;
      this.hideCloseBtn =
        typeof showClose === "undefined" || showClose == null
          ? false
          : !showClose;
      this.dialogTitle = dialogTitle;
      this.showHeader = showHeader;
      this.isClass = dialogData.class ? dialogData.class : "";

      // 返回onClose回调方法的注册
      return this.showDialogResult;
    },
    // 组件内部关闭弹窗事件
    closeDialog(closeBundle) {
      if (closeBundle) {
        this.setCloseBundle(closeBundle);
      }
      this.clickClose = false;
      this.close();
    },
    // 设置弹窗关闭的回调参数
    setCloseBundle(bundle) {
      if (typeof bundle !== "object") {
        console.error(`expected a object, but the bundle is ${bundle}`);
      }
      this.closeBundle = bundle;
    },
    // 设置弹窗关闭
    close() {
      this.visible = false;
    },
    // 弹窗的关闭回调事件
    onClosed() {
      // 等待关闭动画结束。销毁内容组件，下次再弹同一个框时才会调用内容组件的mounted
      setTimeout(() => {
        this.contentComponentDom = null;
        this.callCloseListeners();
      }, 320);
    },
    // 执行弹窗的关闭onClose注册事件
    callCloseListeners() {
      const listeners = this.closeListeners.slice();
      this.closeListeners = [];

      const closeBundle = this.closeBundle;
      const clickClose = this.clickClose;
      this.clickClose = true;
      this.closeBundle = {};

      listeners.forEach((fn) => fn(clickClose, closeBundle));
    },
    // 在子组件内设置弹窗的title
    setTitle(title) {
      this.dialogTitle = title;
    },
    // 加载弹窗的子组件
    setupComponent(dialogDom, dialogData) {
      Vue.component(dialogDom.name, dialogDom);
      this.dialogData = dialogData;
      this.contentComponentDom = dialogDom;
    },
  },
};
</script>

<style lang="scss" rel="stylesheet/scss" scoped>
::v-deep .el-dialog {
  width: fit-content;
  background: rgba(255, 255, 255, 1);
  border-radius: 6px;
  overflow: hidden;
  .el-dialog__header {
    padding: 0 40px 0px 20px;
    height: 50px;
    line-height: 50px;
    font-size: 18px;
    text-align: left;
    color: #333;
    box-sizing: border-box;
    border-bottom: 1px solid #ebeef5;
    .el-dialog__title {
      font-size: 16px;
      font-weight: normal;
      color: rgba(48, 49, 51, 1);
      line-height: 18px;
    }
    .el-dialog__headerbtn {
      top: 15px;
      right: 20px;
      .el-dialog__close {
        font-size: 22px;
        color: #cdd0d8;

        &:hover {
          color: #0068ff;
        }
      }
    }
  }

  .el-dialog__body {
    padding: 15px 0px;
  }
}
.header {
  width: 100%;
  position: absolute;
  top: 0px;
  box-sizing: border-box;
  padding: 10px 15px;
  display: flex;
  justify-content: space-between;
  img {
    width: 57px;
    height: 21px;
  }
  i {
    font-size: 18px;
    font-weight: bolder;
    cursor: pointer;
    &:hover {
      color: #ffa800;
    }
  }
}
</style>
